<!DOCTYPE html>
<html lang="en">
<!---
https://cdn.bootcdn.net/ajax/libs/three.js/0.166.1/three.module.js
比如安装148版本
npm install three@0.148.0 save
-->
<head>
    <meta charset="UTF-8">
    <title>cube-lee</title>
    <script type="importmap">
        {
          "imports": {
            "three": "./js/threejs/three.module.js",
            "three/addons/": "./js/jsm/"
          }
        }
    </script>
    <script src="./js/points.js"></script>
    <script src="./js/pointUtil.js"></script>
<style>
  body {
	  margin: 0;
	  background-color: #000;
	  color: #fff;
	  font-family: Monospace;
	  font-size: 13px;
	  line-height: 24px;
	  overscroll-behavior: none;
  }

  canvas {
      display: block;
  }

  #tooltip {
      position: absolute;
      background-color: rgba(0, 0, 0, 0.7);
      color: white;
      padding: 5px;
      border-radius: 5px;
      display: none;
      /* 默认隐藏 */
      pointer-events: none;
      font-size: 12px;
      white-space: break-spaces;
      z-index: 1;
  }
</style>
</head>
<body>
<!-- 创建用于显示提示的文本元素 -->
<div id="container"></div>
<div id="tooltip" onclick="tooltipCkick"></div>
<script type="module">
	import * as THREE from "./js/threejs/three.module.js";
	import { OrbitControls } from './js/threejs/jsm/controls/OrbitControls.js';
    // 索引数组，定义每个面由哪些顶点构成 (每个面由两个三角形组成)
    const indicesCube = [
            0, 1, 2, 0, 2, 3, // 底面
            4, 6, 5, 4, 7, 6, // 顶面
            0, 4, 5, 0, 5, 1, // 右面
            1, 5, 6, 1, 6, 2, // 前面
            2, 6, 7, 2, 7, 3, // 上面
            3, 7, 4, 3, 4, 0, // 背面
        ];


	var scene,camera,renderer,container;
	var raycaster = new THREE.Raycaster();
    var pointer = new THREE.Vector2();

	initScene();
	render();

    createCubesByData(scene,optCubes);
    var faceIdx = 2;
    testCube(hCube,faceIdx);
    testCube(hCube,faceIdx);

    var oRange = getCubeRange(hCube,1)
    console.log('iWidth=',oRange.width,oRange.height);

    var hCube = null;
    function createCubesByData(hScene,optCubes){
        //场景不能为空
        if(null==hScene || typeof(hScene)=='undefined'){
            return null
        }
         //长方体参数不能为空
        if(null==optCubes || typeof(optCubes)=='undefined' || !(optCubes instanceof Array)){
            return null
        }
        var iCubNum = optCubes.length
        var iCubIdx,optCube
        var oCubes = []
        var oCube;
        console.log('iCubNum=',iCubNum)
        
        for(iCubIdx=0;iCubIdx<iCubNum;iCubIdx++){
            if(iCubIdx!=6){
                continue;
            }
            optCube = optCubes[iCubIdx];
            oCube   = createCubeByData(hScene,optCube)
            if(null==oCube || typeof(oCube)=='undefined'){
                continue
            }
            hCube = oCube;
            console.log('oCube--->',oCube)
            console.log('oCube.userData--->',oCube.userData)
            oCubes.push(oCube);
        }
        return oCubes;
    }
    
    function testCube(hCube,faceIdx){
        console.log('testCube---faceIdx=',faceIdx)
        if(null==hCube || typeof(hCube)=='undefined'){
            return null
        }
        if(null==faceIdx || typeof(faceIdx)!="number"){
            return null
        }
        if(faceIdx<0 || faceIdx>5){
            return null
        }
        
        var materials = hCube.material;
        console.log('testCube---hCube=',hCube)
        console.log('testCube---materials=',materials)
        if(null==materials || typeof(materials)=='undefined' || !(materials instanceof Array)){
            return null
        }
        var hCanvas = null;
        var material = materials[faceIdx];
        var bNew = false;
        var hContext = null;

        
        if(null!=material && typeof(material)!="undefined"){
            hCanvas = material.canvas_;
        }
        if(null==hCanvas){
            var oRange = getCubeRange(hCube,faceIdx)
            if(null==oRange){
                return null;
            }
            
            var vWidth = oRange.width;
            var vheight = oRange.height;
            console.log('testCube---hCanvas is null vWidth=',vWidth,'vheight=',vheight)
            hCanvas = document.createElement('canvas');
            hCanvas.width = vWidth;
            hCanvas.height = vheight;
            hCanvas.style.width = vWidth+'px';
            hCanvas.style.height = vheight+'px';
            hContext = hCanvas.getContext('2d');
            hContext.clearRect(0,0,vWidth,vheight);
            hContext.fillStyle = "rgba(255,255,255,1)";
            hContext.fillRect(0,0,vWidth,vheight);
            if(null!=material && typeof(material)!="undefined"){
                material.canvas_ = hCanvas;
            }
            bNew = true;
        }else{
            console.log('testCube---hCanvas is not null')
            hContext = hCanvas.getContext('2d');
        }
        var vbkColor = 0xFFFF00;
        hContext.fillStyle = vbkColor;
        
        var x = 100
        var y = 100 
        var width = 300;
        var height= 300;
        hContext.fillRect(x, y, width,height);
        if(bNew){
            var texture = new THREE.Texture(hCanvas);
            texture.needsUpdate = true;//, color: 0xff00ff, fog: true
            material = new THREE.MeshPhongMaterial( { map: texture} );
            material.canvas_ = hCanvas;
            materials[faceIdx] = material;
        }else{
            console.log('material--->',material)
        }
        
    }
    function createCubeByData(hScene,optCube){
        var indicesOpt = [
            0, 1, 2, 0, 2, 3, // 底面
            4, 6, 5, 4, 7, 6, // 顶面
            0, 4, 5, 0, 5, 1, // 右面
            1, 5, 6, 1, 6, 2, // 前面
            2, 6, 7, 2, 7, 3, // 上面
            3, 7, 4, 3, 4, 0, // 背面
        ];
        var groups = [
                {"start": 0 ,"count": 6,"materialIndex": 0},
                {"start": 6 ,"count": 6,"materialIndex": 1},
                {"start": 12,"count": 6,"materialIndex": 2},
                {"start": 18,"count": 6,"materialIndex": 3},
                {"start": 24,"count": 6,"materialIndex": 4},
                {"start": 30,"count": 6,"materialIndex": 5}
            ];
        const uvs = new Float32Array([
            // 前面
            0, 1, 1, 1, 1, 0, 0, 0,  // 前面 0,6
            // 后面
            0, 1, 1, 1, 1, 0, 0, 0,  // 后面 6,6
            // 左面
            0, 0, 0, 1, 0, 0, 0, 1,  // 左面 12,6
            // 右面
            0, 1, 1, 1, 1, 0, 0, 0,  // 右面 18,6
            // 底面
            0, 1, 1, 1, 1, 0, 0, 0,  // 底面 24,6
            // 顶面
            0, 1, 1, 1, 1, 0, 0, 0,   // 顶面 30,6
        ]);
        //场景不能为空
        if(null==hScene || typeof(hScene)=='undefined'){
            return null
        }
        //长方体参数不能为空
        if(null==optCube || typeof(optCube)=='undefined'){
            return null
        }
        //长方体坐标点数不少于8个，多余8个只取前面8个
        var points = optCube.points;
        if(null==points || typeof(points)=='undefined' || !(points instanceof Array)){
            return null
        }
        var iPointNum = points.length;
        if(iPointNum<8){
            console.log('长方体的坐标点少于8个')
            return null
        }
        //长方体数据
        var data = optCube.data;
        if(null==data || typeof(data)=='undefined'){
            optCube.data = {}
            data = optCube.data;
        }
        var vertices = pointsToVertices8(points);
        showVerticesEx(vertices)
        var attribue = new THREE.BufferAttribute(vertices, 3);   

        // 创建一个长方体的BufferGeometry
        var geometry = new THREE.BufferGeometry();
        geometry.setIndex(indicesOpt);
        geometry.attributes.position = attribue;
        geometry.computeVertexNormals(); // 计算法线，确保光照正常

        var material1 = new THREE.MeshPhongMaterial( { color: 0x0000FF,side: THREE.DoubleSide} );
        var material2 = new THREE.MeshPhongMaterial( { color: 0xA52A2A,side: THREE.DoubleSide} );
        var material3 = new THREE.MeshPhongMaterial( { color: 0x7FFF00,side: THREE.DoubleSide} );
        var material4 = new THREE.MeshPhongMaterial( { color: 0xDC143C,side: THREE.DoubleSide} );
        var material5 = new THREE.MeshPhongMaterial( { color: 0x00008B,side: THREE.DoubleSide} );
        var material6 = new THREE.MeshPhongMaterial( { color: 0xFF00FF,side: THREE.DoubleSide} );
        let materials = [material1,material2,material3,material4,material5,material6];
        var mesh = new THREE.Mesh(geometry, materials);
        mesh.geometry.groups = groups;
        mesh.castShadow = true;
        mesh.userData   = data;
        // 将长方体添加到场景
        hScene.add(mesh);
        return mesh;
    }

    //求长方体面的长宽
    function getCubeRange(hCube,faceIdx){
        if(null==hCube || typeof(hCube)=='undefined'){
            return null
        }
        if(null==faceIdx || typeof(faceIdx)!="number"){
            return null
        }
        if(faceIdx<0 || faceIdx>5){
            return null
        }
        var hGeometry = null;
        if(hCube instanceof THREE.Mesh){
            hGeometry = hCube.geometry
        }else if(hCube instanceof THREE.BufferGeometry){
            hGeometry = hCube
        }
        if(null==hGeometry){
            return null
        }
        var hAttributes = hGeometry.attributes;
        if(null==hAttributes || typeof(hAttributes)=='undefined'){
            return null
        }
        var positions = hAttributes.position;
        if(null==positions || typeof(positions)=='undefined'){
            return null
        }
        var pArr= positions.array
        if(null==pArr|| typeof(pArr)=='undefined'){
            return null
        }
        
        /*
        0, 1, 2, 0, 2, 3, // 底面
        4, 6, 5, 4, 7, 6, // 顶面
        0, 4, 5, 0, 5, 1, // 右面
        1, 5, 6, 1, 6, 2, // 前面
        2, 6, 7, 2, 7, 3, // 左面
        3, 7, 4, 3, 4, 0, // 背面
        */
        var x1,y1,z1
        var x2,y2,z2
        var x3,y3,z3
        var x4,y4,z4
        var rWidth  = 0
        var rHeight = 0
        
        var iSize = positions.array.length;
        var faceDesc=''
        switch (faceIdx) {
            case 0: //0, 1, 2, 0, 2, 3, // 底面
                x1 = pArr[0]
                y1 = pArr[1]
                z1 = pArr[2]
                x2 = pArr[3]
                y2 = pArr[4]
                z2 = pArr[5]
                x3 = pArr[6]
                y3 = pArr[7]
                z3 = pArr[8]
                x4 = pArr[9]
                y4 = pArr[10]
                z4 = pArr[11]
                faceDesc='底面 0, 1, 2'
                rWidth  = Math.sqrt(Math.pow(x4-x1,2)+Math.pow(y4-y1,2)+Math.pow(z4-z1,2))
                rHeight = Math.sqrt(Math.pow(x2-x3,2)+Math.pow(y2-y3,2)+Math.pow(z2-z3,2))
                break;
            case 1: //4, 6, 5, 4, 7, 6, // 顶面
                x1 = pArr[12]
                y1 = pArr[13]
                z1 = pArr[14]
                x2 = pArr[18]
                y2 = pArr[19]
                z2 = pArr[20]
                x3 = pArr[15]
                y3 = pArr[16]
                z3 = pArr[17]
                x4 = pArr[21]
                y4 = pArr[22]
                z4 = pArr[23]
                faceDesc='顶面 4, 6, 5'
                rWidth  = Math.sqrt(Math.pow(x4-x1,2)+Math.pow(y4-y1,2)+Math.pow(z4-z1,2))
                rHeight = Math.sqrt(Math.pow(x2-x3,2)+Math.pow(y2-y3,2)+Math.pow(z2-z3,2))
                break;
            case 2://0, 4, 5, 0, 5, 1, // 前面
                x1 = pArr[0]
                y1 = pArr[1]
                z1 = pArr[2]
                x2 = pArr[12]
                y2 = pArr[13]
                z2 = pArr[14]
                x3 = pArr[15]
                y3 = pArr[16]
                z3 = pArr[17]
                x4 = pArr[3]
                y4 = pArr[4]
                z4 = pArr[5]
                faceDesc='前面 0, 4, 5'
                rWidth  = Math.sqrt(Math.pow(x4-x1,2)+Math.pow(y4-y1,2)+Math.pow(z4-z1,2))
                rHeight = Math.sqrt(Math.pow(x4-x3,2)+Math.pow(y4-y3,2)+Math.pow(z4-z3,2))
                break;
            case 3: //1, 5, 6, 1, 6, 2, // 右面
                x1 = pArr[3]
                y1 = pArr[4]
                z1 = pArr[5]
                x2 = pArr[15]
                y2 = pArr[16]
                z2 = pArr[17]
                x3 = pArr[18]
                y3 = pArr[19]
                z3 = pArr[20]
                x4 = pArr[6]
                y4 = pArr[7]
                z4 = pArr[8]
                faceDesc='右面 1, 5, 6'
                rWidth  = Math.sqrt(Math.pow(x2-x3,2)+Math.pow(y2-y3,2)+Math.pow(z2-z3,2))
                rHeight = Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2)+Math.pow(z2-z1,2))
                break;
            case 4: //2, 6, 7, 2, 7, 3, // 背面
                x1 = pArr[3]
                y1 = pArr[4]
                z1 = pArr[5]
                x2 = pArr[18]
                y2 = pArr[19]
                z2 = pArr[20]
                x3 = pArr[21]
                y3 = pArr[22]
                z3 = pArr[23]
                x4 = pArr[9]
                y4 = pArr[10]
                z4 = pArr[11]
                faceDesc='背面 2, 6, 7'
                rWidth  = Math.sqrt(Math.pow(x2-x3,2)+Math.pow(y2-y3,2)+Math.pow(z2-z3,2))
                rHeight = Math.sqrt(Math.pow(x4-x3,2)+Math.pow(y4-y3,2)+Math.pow(z4-z3,2))
                break;
            case 5://3, 7, 4, 3, 4, 0, //左面
                x1 = pArr[9]
                y1 = pArr[10]
                z1 = pArr[11]
                x2 = pArr[21]
                y2 = pArr[22]
                z2 = pArr[23]
                x3 = pArr[12]
                y3 = pArr[13]
                z3 = pArr[14]
                x4 = pArr[0]
                y4 = pArr[1]
                z4 = pArr[2]
                faceDesc='左面 3, 7, 4'
                rWidth  = Math.sqrt(Math.pow(x2-x3,2)+Math.pow(y2-y3,2)+Math.pow(z2-z3,2))
                rHeight = Math.sqrt(Math.pow(x4-x3,2)+Math.pow(y4-y3,2)+Math.pow(z4-z3,2))
                break;
        }
        // console.log('faceIdx=',faceIdx,'faceDesc=',faceDesc,'iSize=',iSize,'rWidth=',rWidth,'rHeight=',rHeight,'(',x1,',',y1,',',z1,'),','(',x2,',',y2,',',z2,'),','(',x3,',',y3,',',z3,'),','(',x4,',',y4,',',z4,'),');
        var p0 = faceIdx*6 + 0;
        var p1 = p0 + 1;
        var p2 = p0 + 2;
        return {width:rWidth,height:rHeight};
    }
    

	//初始化场景
	function initScene(){
		// 创建场景
		scene = new THREE.Scene();
		scene.background = new THREE.Color(0x000000)

        container = document.getElementById( 'container' );
		// 创建相机
		camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 10000);
		// camera.position.x = -300;
        camera.position.y = -500;
        camera.position.z += 900;

		// 创建渲染器
		renderer = new THREE.WebGLRenderer({ antialias: true });
		// 渲染器能够渲染阴影效果
		renderer.shadowMap.enabled = true;
        renderer.setSize( window.innerWidth, window.innerHeight );
        container.appendChild(renderer.domElement);


		// 添加网格辅助器
		const gridHelper = new THREE.GridHelper(5000, 50); // 创建一个200单位的网格，细分为50个方格
		gridHelper.rotation.x = 0.5 * Math.PI
        //gridHelper.position.y = -150;
		scene.add(gridHelper);

		// 方向光
		const directionalLight = new THREE.DirectionalLight(0xFFFFFF, 1);
		directionalLight.position.set(10, 10, 10);

		directionalLight.shadow.mapSize.width = 1024  // default
		directionalLight.shadow.mapSize.height = 1024  // default
		directionalLight.shadow.camera.near = 0.05  // default
		directionalLight.shadow.camera.far = 500  // default
		//将范围调大
		directionalLight.shadow.camera.top = 20 /// 这个是生效的属性
		directionalLight.shadow.camera.right = 20
		directionalLight.shadow.camera.left = -20
		directionalLight.shadow.camera.bottom = -20
		directionalLight.castShadow = true;
		scene.add(directionalLight);

		// 环境光
		const ambientLight = new THREE.AmbientLight(0xffffff, 2);
		scene.add(ambientLight);

		// 添加鼠标控制
		const controls = new OrbitControls(camera, renderer.domElement);
		// controls.enableDamping = true; // 使得相机移动更加平滑
		controls.dampingFactor = 0.05; // 阻尼效果

        window.addEventListener( 'pointerup', onPointerUp );
        window.addEventListener( 'resize', onWindowResize, false );
	}

    function onPointerUp( event ) {

        // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)

        pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

        raycaster.setFromCamera( pointer, camera );

        // 计算物体和射线的焦点
        const intersects = raycaster.intersectObjects( scene.children );
		if(intersects.length>0) {
			let intersectObj = intersects[ 0 ];
            if( intersectObj.uv ) {
                let optItem,faceItem,bcheck=false;

                let uvx = intersectObj.uv.x * optparams.size.x;
                let uvy = (1-intersectObj.uv.y) * optparams.size.y;

                for(let i=0;i<gOptArry.length;i++) {
                    optItem = gOptArry[i];

                    if( optItem.faceIdx==intersectObj.face.materialIndex ) {

                        for(let j=0;j<optItem.size.length;j++) {
                            faceItem = optItem.size[j];
                            if( faceItem.postion[0].x<=uvx && faceItem.postion[0].y<=uvy &&
                                (faceItem.postion[0].x+faceItem.postion[1].x)>=uvx && (faceItem.postion[0].y+faceItem.postion[1].y)>=uvy) {
                                bcheck=true;
                                console.log('拾取第'+(i+1)+'图片');
                                alert(faceItem.title);
                                break;
                            }
                        }

                    }
                }

                if(!bcheck) {
                    alert(getDatetime());
				}
			}
        }

    }

    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize( window.innerWidth, window.innerHeight );

    }

	function render() {
		// 渲染
		requestAnimationFrame(render);
		renderer.render(scene, camera);
	}

</script>

</body>
</html>
